home *** CD-ROM | disk | FTP | other *** search
/ Young Minds / Young Minds Interactive CD-ROM.ISO / sdi / pr_helpe.c < prev    next >
Encoding:
C/C++ Source or Header  |  1987-06-18  |  6.3 KB  |  234 lines

  1. /****************************  pr_helpers.c  *************************/
  2. #include <pixrect/pixrect_hs.h>
  3.  
  4. /*
  5.  * Copyright 1987 by Mark Weiser.
  6.  * Permission to reproduce and use in any manner whatsoever on Suns is granted
  7.  * so long as this copyright and other identifying marks of authorship
  8.  * in the code and the game remain intact and visible.  Use of this code
  9.  * in other products is reserved to me--I'm working on Mac and IBM versions.
  10.  */
  11.  
  12. /* These routines are pure pixrect operators, used mostly for city operations */
  13.  
  14. static short pattern[] = {
  15.     0x8000, 0x4000, 0x2000, 0x1000, 0x800, 0x400, 0x200, 0x100,
  16.     0x80,   0x40,   0x20,   0x10,   0x8,   0x4,   0x2,   0x1
  17.     };
  18. static short *end_of_pattern_ptr = &pattern[16];
  19.  
  20.  
  21. #define lefthalf(x) (((x) & 0xff00) >> 8)
  22. #define righthalf(x) ((x) & 0xff)
  23.  
  24. /*
  25.  * Does an incremental melt of old into target, replacing
  26.  * old, by dropping pixels down until they hit target
  27.  * pixels.  Melts 'speed' pixels per call.  Old and target should be
  28.  * memory pixrects.  Probably won't work as written for color.
  29.  *
  30.  * Pretty dumb and slow, undoubtedly could be done better.
  31.  */
  32.  
  33. /* alg: drop topmost pixels by speed pixels.  Any pixels which were on
  34.    in the old which matched on's in the target, still stay on.
  35.    Warning: the speed parameter does not work for any value but 1.
  36.  */
  37.  
  38.  
  39. melt(old, target, speed)
  40. struct pixrect *old, *target;
  41. int speed;
  42. {
  43.     short x_count, y_count, max_x, count, base = 0, bit_count;
  44.     int w = old->pr_size.x, h = old->pr_size.y;
  45.     struct pixrect *final;
  46.     struct mpr_data *mpr_final, *mpr_old;
  47.     short num_shorts, speed_inc;
  48.     short *old_image, *final_image;
  49.     unsigned short *remember_all_bits;
  50.     unsigned short *remember_bits, *bit_ptr;
  51.     register short *pattern_ptr, *old_image_ptr, *final_image_ptr;
  52.  
  53.     if (w != target->pr_size.x || h != target->pr_size.y) {
  54.         /* never leave here */
  55.         printf("melt requires equal size pixrects.\n");
  56.         abort();
  57.     }
  58.  
  59.     mpr_old = mpr_d(old);
  60.  
  61.     if (mpr_old->md_offset.x != 0 || mpr_old->md_offset.y != 0) {
  62.         /* Never leave here */
  63.         printf("Can't handle region pixrects in 'melt'.\n");
  64.         abort();
  65.     };
  66.  
  67.     final = mem_create(w, h, 1);
  68.  
  69.     /* see if there is any work to do */
  70.     pr_rop(final, 0, 0, w, h, PIX_SRC, old, 0, 0);
  71.     pr_rop(final, 0, 0, w, h, PIX_NOT(PIX_SRC) & PIX_DST, target, 0, 0);
  72.     if (all_zero_bits(final)) {
  73.         pr_destroy(final);
  74.         return;
  75.     }
  76.     
  77.     /* remember what was ok from before */
  78.     pr_rop(final, 0, 0, w, h, PIX_SRC, old, 0, 0);
  79.     pr_rop(final, 0, 0, w, h, PIX_SRC & PIX_DST, target, 0, 0);
  80.     
  81.     /* melt some bits */
  82.  
  83.     mpr_final = mpr_d(final);
  84.     num_shorts = mpr_final->md_linebytes / 2;
  85.     speed_inc = num_shorts*speed;
  86.     final_image = mpr_final->md_image;
  87.     old_image = mpr_old->md_image;
  88.     remember_all_bits = (unsigned short *)calloc(num_shorts+1, 2);
  89.     remember_bits = (unsigned short *)calloc(w+1, 2);
  90.  
  91.     /* Melt the top */
  92.     for(y_count = 0; y_count < h - speed; y_count += 1) {
  93.         if (all_ones(remember_all_bits, num_shorts))
  94.             goto next;
  95.         bit_ptr = remember_bits;
  96.         old_image_ptr = &old_image[base];
  97.         final_image_ptr = &final_image[base];
  98.         for (x_count = 0; x_count < num_shorts; x_count += 1) {
  99.             remember_all_bits[x_count] |= *old_image_ptr;
  100.             for(pattern_ptr = pattern; pattern_ptr < end_of_pattern_ptr; pattern_ptr++) {
  101.                 /* for each bit... */
  102.                 if (*old_image_ptr & *pattern_ptr) {
  103.                     /* if you saw one in this 'x' position before... */
  104.                     if (*bit_ptr) {
  105.                         /* just copy this one in place. */
  106.                         *final_image_ptr |= *pattern_ptr;
  107.                     } else {
  108.                         /* if this one is the first one here, melt it. */
  109.                         *bit_ptr = 1;
  110.                         *(final_image_ptr+speed_inc) |= *pattern_ptr;
  111.                     }
  112.                 }
  113.                 bit_ptr++;
  114.             } 
  115.             old_image_ptr++;
  116.             final_image_ptr++;
  117.         }
  118.     base += num_shorts;
  119.     }
  120.  
  121.     /* Move the rest of the image as is */
  122. next:
  123.     for(; y_count < h - speed; y_count += 1) {
  124.         old_image_ptr = &old_image[base];
  125.         final_image_ptr = &final_image[base];
  126.         for (x_count = 0; x_count < num_shorts; x_count += 1) {
  127.             *final_image_ptr |= *old_image_ptr;
  128.             old_image_ptr++;
  129.             final_image_ptr++;
  130.         }
  131.     base += num_shorts;
  132.     }
  133.  
  134.  
  135.     /* return value in old */
  136.     pr_rop(old, 0, 0, w, h, PIX_SRC, final, 0, 0);
  137.     pr_destroy(final);
  138.     free(remember_bits);
  139.     free(remember_all_bits);
  140. }
  141.  
  142.  
  143. static lookup[] = {
  144. #include "lookup.h"
  145. };    
  146.  
  147. /*
  148.  * Count the number of bits in a pixrect.
  149.    Not tested on, and may not work for, color.
  150.  */
  151. count_bits(pr)
  152. struct pixrect *pr;        /* should be a memory pixrect for dvc ind. */
  153. {
  154.     register short x_count, y_count, max_x, count, base = 0, num_shorts;
  155.     struct mpr_data *mpr = mpr_d(pr);
  156.     if (mpr->md_offset.x != 0 || mpr->md_offset.y != 0) {
  157.         /* Never leave here */
  158.         printf("Can't handle region pixrects in 'count_bits'.\n");
  159.         abort();
  160.     };
  161.     count = 0;
  162.     num_shorts = mpr->md_linebytes / 2;
  163.     for(y_count = 0; y_count < pr->pr_size.y; y_count++) {
  164.         for (x_count = 0; x_count < num_shorts; x_count += 1) {
  165.             count += lookup[lefthalf(mpr->md_image[base+x_count])]
  166.                 +lookup[righthalf(mpr->md_image[base+x_count])];
  167.         }
  168.         base += num_shorts;
  169.     }
  170.     return count;
  171. }
  172.  
  173. /*
  174.  * See if a memory pixrect is all zero.
  175.  */
  176. all_zero_bits(pr)
  177. struct pixrect *pr;        /* should be a memory pixrect */
  178. {
  179.     register short x_count, y_count, max_x, count, base = 0, num_shorts;
  180.     struct mpr_data *mpr = mpr_d(pr);
  181.     if (mpr->md_offset.x != 0 || mpr->md_offset.y != 0) {
  182.         /* Never leave here */
  183.         printf("Can't handle region pixrects in 'count_bits'.\n");
  184.         abort();
  185.     };
  186.     count = 0;
  187.     num_shorts = mpr->md_linebytes / 2;
  188.     for(y_count = 0; y_count < pr->pr_size.y; y_count++) {
  189.         for (x_count = 0; x_count < num_shorts; x_count += 1) {
  190.             if (mpr->md_image[base+x_count])
  191.                 return 0;
  192.         }
  193.         base += num_shorts;
  194.     }
  195.     return 1;
  196. }
  197.  
  198. /*
  199.  * See if an array of shorts contains all ones.
  200.  */
  201. all_ones(x, len)
  202. register len;
  203. register unsigned short *x;
  204. {
  205.     for(; len; len--) {
  206.         if (*x++ != 0xffff) {
  207.             return 0;
  208.         }
  209.     }
  210.     return 1;
  211. }
  212.  
  213.  
  214. /*
  215.  * Grow could, and possibly should, be made to work like melt, and
  216.  * grow only at the edge of black areas, but growing linearly up
  217.  * from the bottom looks ok too. (Which is not true in revese for melting!).
  218.  * Unfortunately they are now asymmetrical, because grow needs a 'position'
  219.  * parameter which says how far from the bottom we are.
  220.  *
  221.  * Grow only works for 64x64 bit pixrects (because of hardwired constants),
  222.  * unlike melt which can melt anything.
  223.  */
  224.  
  225. grow(old, target, position)
  226. struct pixrect *old, *target;
  227. {
  228.     if (position < 1 || position > 64)
  229.         return;
  230.     pr_rop(old, 0, 64 - position, 64, position, PIX_SRC,
  231.         target, 0, 64 - position); 
  232. }
  233.  
  234.